/*
 * Copyright (c) 2009 DeledImporter
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'Pyro Games' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package net.pyrogames.deled.light;

import net.pyrogames.deled.geometry.DXSSpatial;
import net.pyrogames.deled.material.DXSColorRGBA;

/**
 * A fundamental DXS scene element (other than a DXSPrimitive)
 * that represents a light element in the scene.
 * <p>
 * All lights share common attributes as defined in this class,
 * but specific lights subclass such as <code>{@link DXSPointLight}</code>,
 * <code>{@link DXSSpotLight}</code>, and <code>{@link DXSDirectionalLight}</code>.
 * 
 * @author Nicholas Woodfield
 *
 */
public abstract class DXSLight extends DXSSpatial {
	
	public enum Type{
		Directional,
        Point,
        Spot
	}
	/** Ambient color of the light */
	private DXSColorRGBA ambient;
	/** Diffuse color of the light */
	private DXSColorRGBA diffuse;
	/** Specular color of the light */
	private DXSColorRGBA specular;
	
	/** True if the light attenuates */
	private boolean attenuate;
	/** Constant value in the light equation */
	private float constant;
	/** Linear value in the light equation */
	private float linear;
	/** Quadratic value in the light equation */
	private float quadratic;
	
	/**  True if this light should cast shadows */
	private boolean shadowCaster;
	/** True if this light is on */
	private boolean enabled;
	
	/**
	 * Creates a default light, with colors set to white
	 */	
	public DXSLight(String title){
		super(title);
		ambient = new DXSColorRGBA(.4f,.4f,.4f,1.0f);
		diffuse = new DXSColorRGBA();
		specular = new DXSColorRGBA();
	}
	
	/**
	 * Get the type of light, implemented 
	 * by a subclass.
	 * 
	 * @return
	 * 		LightType
	 */
	public abstract Type getType();
	
	/**
	 * Get the ambient color
	 * 
	 * @return
	 * 		<code>DXSColorRGBA</code>
	 */
	public DXSColorRGBA getAmbient(){
		return ambient;
	}
	
	/**
	 * Set the ambient color
	 * 
	 * @param a	<code>DXSColorRGBA</code>
	 */
	public void setAmbient(DXSColorRGBA a){
		ambient.r = a.r;
		ambient.g = a.g;
		ambient.b = a.b;
		ambient.a = a.a;
	}
	
	/**
	 * Get the diffuse color.
	 * 
	 * @return
	 * 		<code>DXSColorRGBA</code>
	 */
	public DXSColorRGBA getDiffuse(){
		return diffuse;
	}
	
	/**
	 * Set the diffuse color.
	 * 
	 * @param d <code>DXSColorRGBA</code>
	 */
	public void setDiffuse(DXSColorRGBA d){
		diffuse.r = d.r;
		diffuse.g = d.g;
		diffuse.b = d.b;
		diffuse.a = d.a;
	}
	
	/**
	 * Get the specular color.
	 * 
	 * @return
	 * 		<code>DXSColorRGBA</code>
	 */
	public DXSColorRGBA getSpecular(){
		return specular;
	}
	
	/**
	 * Set the specular color.
	 * 
	 * @param s
	 * 		<code>DXSColorRGBA</code>
	 */
	public void setSpecular(DXSColorRGBA s){
		specular.r = s.r;
		specular.g = s.g;
		specular.b = s.b;
		specular.a = s.a;
	}
	
	/**
	 * Set if this light should attenuate
	 * 
	 * @param a
	 * 		true if attenuates, false otherwise
	 */
	public void setAttenuate(boolean a){
		attenuate = a;
	}
	
	/**
	 * If the light attenuates or not.
	 * 
	 * @return
	 * 		True if attenuates, false otherwise
	 */
	public boolean isAttenuate(){
		return attenuate;
	}
	
	/**
	 * Set the constant value for this light.
	 * 
	 * @param c
	 * 		float
	 */
	public void setConstant(float c){
		constant = c;
	}
	
	/**
	 * Get the constant value for this light.
	 * 
	 * @return
	 * 		float value
	 */
	public float getConstant(){
		return constant;
	}
	
	/**
	 * Set the linear value for this light.
	 * 
	 * @param l
	 * 		float value
	 */
	public void setLinear(float l){
		linear = l;
	}
	
	/**
	 * Get the linear value for this light.
	 * 
	 * @return
	 * 		float value
	 */
	public float getLinear(){
		return linear;
	}
	
	/**
	 * Set the quadratic value for this light.
	 * 
	 * @param q
	 * 		float value
	 */
	public void setQuadratic(float q){
		quadratic = q;
	}
	
	/**
	 * Get the quadratic value for this light.
	 * 
	 * @return
	 * 		float value
	 */
	public float getQuadratic(){
		return quadratic;
	}
	
	/**
	 * Set if this light should cast shadows.
	 * 
	 * @param shadow
	 * 		true if it should, false otherwise
	 */
	public void setShadowCaster(boolean shadow){
		shadowCaster = shadow;
	}
	
	/**
	 * See if this light is a shadow caster.
	 * 
	 * @return
	 * 		true if so, false otherwise
	 */
	public boolean isShadowCaster(){
		return shadowCaster;
	}
	
	/**
	 * Set if this light should be enabled.
	 * 
	 * @param e
	 * 		true if it should be, false otherwise
	 */
	public void setEnabled(boolean e){
		enabled = e;
	}
	
	/**
	 * See if this light is enabled.
	 * 
	 * @return
	 * 		true if its enabled, false otherwise
	 */
	public boolean isEnabled(){
		return enabled;
	}

}
